package com.youxin.task.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.youxin.base.TPage;
import com.youxin.base.TResult;
import com.youxin.task.entity.enums.ScheduleStatus;
import com.youxin.task.entity.req.JobSearch;
import com.youxin.task.entity.vo.JobVo;
import com.youxin.task.mapper.JobMapper;
import com.youxin.task.model.Job;
import com.youxin.task.service.JobService;
import com.youxin.task.util.ScheduleUtils;
import org.quartz.CronExpression;
import org.quartz.CronTrigger;
import org.quartz.Scheduler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * description: JobServiceImpl <br>
 * date: 2020/3/6 16:26 <br>
 * author: llkj <br>
 * version: 1.0 <br>
 */
@Service
public class JobServiceImpl extends ServiceImpl<JobMapper, Job> implements JobService {

    @Autowired
    private Scheduler scheduler;

    /**
     * 项目启动时，初始化定时器
     */
    @PostConstruct
    public void init() {
        List<Job> scheduleJobList = list();
        // 如果不存在，则创建
        scheduleJobList.forEach(scheduleJob -> {
            CronTrigger cronTrigger = ScheduleUtils.getCronTrigger(scheduler, scheduleJob.getJobId());
            if (cronTrigger == null) {
                ScheduleUtils.createScheduleJob(scheduler, scheduleJob);
            } else {
                ScheduleUtils.updateScheduleJob(scheduler, scheduleJob);
            }
        });
    }

    @Override
    public TPage<JobVo> findJob(JobSearch jobSearch) {
        IPage page =  this.baseMapper.findJob(new Page<>(jobSearch.getCurrentPage(),jobSearch.getShowCount()),jobSearch);
        return TPage.page(page.getRecords(),page.getTotal());
    }

    @Override
    public int updateBatch(List<String> jobIds, String status) {
        Job job = new Job();
        job.setStatus(status);
        return this.baseMapper.update(job, new LambdaQueryWrapper<Job>().in(Job::getJobId, jobIds));    }

    @Override
    public TResult<Boolean> checkCron(String cron) {
        boolean flag = CronExpression.isValidExpression(cron);
        return TResult.success(flag);
    }

    @Override
    public TResult<String> createJob(JobVo jobDto) {
        Job job = JSONObject.parseObject(JSONObject.toJSONString(jobDto),Job.class);
        job.setStatus(ScheduleStatus.PAUSE.getValue());
        job.setCreateTime(new Date());
        save(job);
        ScheduleUtils.createScheduleJob(scheduler, job);
        return TResult.success();    }

    @Override
    public TResult<String> updateJob(JobVo jobDto) {
        Job job = JSONObject.parseObject(JSONObject.toJSONString(jobDto),Job.class);
        ScheduleUtils.updateScheduleJob(scheduler, job);
         updateById(job);
        return TResult.success();
    }

    @Override
    public TResult<String> runJob(String jobIds) {
        String[] list = jobIds.split(",");
        Arrays.stream(list).forEach(jobId -> ScheduleUtils.run(scheduler, getById(Integer.parseInt(jobId))));
        return TResult.success();    }

    @Override
    public TResult<String> pauseJob(String jobIds) {
        String[] list = jobIds.split(",");
        Arrays.stream(list).forEach(jobId -> ScheduleUtils.pauseJob(scheduler, Long.valueOf(jobId)));
        updateBatch(Arrays.asList(list),ScheduleStatus.PAUSE.getValue());
        return TResult.success();    }

    @Override
    public TResult<String> resumeJob(String jobIds) {
        String[] list = jobIds.split(",");
        Arrays.stream(list).forEach(jobId -> ScheduleUtils.resumeJob(scheduler, Long.valueOf(jobId)));
        updateBatch(Arrays.asList(list),ScheduleStatus.NORMAL.getValue());
        return TResult.success();    }

    @Override
    public TResult<String> deleteJob(String jobIds) {
        String[] list = jobIds.split(",");
        Arrays.stream(list).forEach(jobId -> ScheduleUtils.deleteScheduleJob(scheduler, Long.valueOf(jobId)));
        removeByIds(Arrays.asList(list));
        return TResult.success();
    }
}
